package com.se.utils;

import com.se.common.*;
import com.se.exception.FileConnectionException;
import com.se.mainView.MainViewController;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.IndexRange;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import static com.se.common.Constant.AT_MESSAGE;
import static com.se.common.Constant.FILE_MESSAGE;

//超级无敌大屎山
/**
 * 服务工具类 - 用于管理服务器配置和客户端连接
 */
public class ServiceUtils {
    private static final Properties serverProperties = new Properties();
    public static String serverAddress;
    public static int serverPort;
    private static final ConcurrentHashMap<String, ClientConnectThread>
            connectionMap = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<String, ClientMessage>
            currentAIMessagesMap = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<String, Thread>
            updatingListMap = new ConcurrentHashMap<>();

    private static final ConcurrentHashMap<String, Integer>
            updatingMessageIndex = new ConcurrentHashMap<>();

    private static final ConcurrentHashMap<String, SpecialStyleMessage>
            currentSpecialStyleMessages = new ConcurrentHashMap<>();

    private static final ConcurrentHashMap<Integer, Integer>
            currentSpecialStyleMessageNum = new ConcurrentHashMap<>();

    private static final ConcurrentHashMap<UsernameOrGroupId, ObservableList<ClientMessage>>
            messageTables = new ConcurrentHashMap<>();

    private static final ObservableList<User> userList = FXCollections.observableArrayList();
    private static User speaker;
    private static User chatUser = new User();
    private static Group chatGroup = new Group();
    private static final ObservableList<ClientMessage> messageList = FXCollections.observableArrayList();
    private static final ObservableList<Group> groupList = FXCollections.observableArrayList();
    private static final ObservableList<String> friendRequestList = FXCollections.observableArrayList();
    public static final DateTimeFormatter formatter =
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.CHINA);

    private static Path filePath;
    public static final String fileName = "userProperties.properties";

    public static String APIKEY;
    public static String AITYPE;
    public static String MODEL;
    public static boolean AUTO_DETECT_TEXT;
    public static int MAX_DETECT_NUM;
    public static String FILE_STORAGE_PATH;

    private ServiceUtils(){
    }

    static {
        currentSpecialStyleMessageNum.put(FILE_MESSAGE, 0);
        currentSpecialStyleMessageNum.put(AT_MESSAGE, 0);

        try(InputStream input = ServiceUtils.class.getResourceAsStream("/socket.properties")){
            serverProperties.load(input);
            serverAddress = serverProperties.getProperty("server.address");
            serverPort = Integer.parseInt(serverProperties.getProperty("server.port"));
            initAIProperties();
        } catch (IOException e) {
            /*
            * 后续修改为弹窗
            * */
            e.printStackTrace();
        }
    }

    public static void addFriendRequest(String username) {
        Platform.runLater(() -> friendRequestList.add(username));
    }

    public static void removeFriendRequest(String username) {
        Platform.runLater(() -> friendRequestList.remove(username));
    }

    public static ObservableList<String> getFriendRequestList() {
        return friendRequestList;
    }

    public static void clearUpdatingMessage() {
        currentAIMessagesMap.forEach((key, value) -> value.setComplete());
        currentAIMessagesMap.clear();
        updatingMessageIndex.clear();
        updatingListMap.clear();
    }

    public static void addMessageTable(UsernameOrGroupId key, ObservableList<ClientMessage> value) {
        Platform.runLater(() -> messageTables.put(key, value));
    }

    public static ObservableList<ClientMessage> getMessageTable(UsernameOrGroupId key) {
        return messageTables.get(key);
    }

    public static void insertMessageIntoMessageTables(UsernameOrGroupId key, Message message) {
        if(messageTables.get(key) == null) {
            ObservableList<ClientMessage> messages = FXCollections.observableArrayList(new ClientMessage(message));
            messageTables.put(key, messages);
        }
        else {
           messageTables.get(key).add(new ClientMessage(message));
        }
    }

    public static void insertMessageIntoMessageTables(UsernameOrGroupId key, ClientMessage message) {
        if(messageTables.get(key) == null) {
            ObservableList<ClientMessage> messages = FXCollections.observableArrayList(message);
            messageTables.put(key, messages);
        }
        else {
            messageTables.get(key).add(message);
        }
    }

    public static UsernameOrGroupId getTheOtherOne(Message message) {
        if(isInteger(message.getSendUser())) {
            return new UsernameOrGroupId(message.getSendUser());
        }

        if(isInteger(message.getReceiveUser())) {
            return new UsernameOrGroupId(message.getReceiveUser());
        }

        if(!message.getSendUser().equals(getSpeaker().getUserName())) {
            return new UsernameOrGroupId(message.getSendUser());
        }
        else {
            return new UsernameOrGroupId(message.getReceiveUser());
        }
    }

    public static UsernameOrGroupId getTheOtherOne(ClientMessage message) {
        if(isInteger(message.getSendUser())) {
            return new UsernameOrGroupId(message.getSendUser());
        }

        if(isInteger(message.getReceiveUser())) {
            return new UsernameOrGroupId(message.getReceiveUser());
        }

        if(!message.getSendUser().equals(getSpeaker().getUserName())) {
            return new UsernameOrGroupId(message.getSendUser());
        }
        else {
            return new UsernameOrGroupId(message.getReceiveUser());
        }
    }

    public static void addFileMessage(String fileName, FileMessage fileMessage) {
        //对计数器进行加一，这个函数不是很好懂，主要是防止出现空指针（但感觉好像不会出现
        currentSpecialStyleMessageNum.merge(FILE_MESSAGE, 1, Integer::sum);
        currentSpecialStyleMessages.put(fileName, fileMessage);
    }

    public static void addAtMessage(String username, AtMessage atMessage) {
        currentSpecialStyleMessageNum.merge(AT_MESSAGE, 1, Integer::sum);
        currentSpecialStyleMessages.put(username, atMessage);
    }

    //使用在codeArea中的索引删除，因为预计只会在监听codeArea的delete行为时调用该函数
    public static void rmSpecialStyleMessage(int index) {

        String result = currentSpecialStyleMessages.search(1, (key, value) -> {
            if(value.getRightIndex() >= index && value.getLeftIndex() <= index) {

                if(value instanceof FileMessage) {
                    currentSpecialStyleMessageNum.compute(FILE_MESSAGE,
                            (k, fileNum) -> fileNum != null ? fileNum - 1 : 0);
                }
                else {
                    currentSpecialStyleMessageNum.compute(AT_MESSAGE,
                            (k, num) -> num != null ? num - 1 : 0);
                }
                return key;
            }
            return null;
        });

        if(result != null) {
            System.out.println("删除了新的特殊消息: " + result);
            currentSpecialStyleMessages.remove(result);
        }

    }

    public static IndexRange isInsertInSpecialStyleMessage(int index) {
        AtomicReference<IndexRange> range = new AtomicReference<>();
        range.set(null);
        currentSpecialStyleMessages.forEach((key, value) -> {
            if(value.getLeftIndex() < index && value.getRightIndex() > index) {
                range.set(new IndexRange(value.getLeftIndex(), value.getRightIndex()));
            }
        });

        return range.get();
    }

    //使用索引检查是否删除了特殊文本
    public static IndexRange isSpecialStyleMessageShouldBeRemoved(int index) {
        AtomicInteger left = new AtomicInteger(-1);
        AtomicInteger right = new AtomicInteger(-1);
        currentSpecialStyleMessages.forEach((key, value) -> {
            if(value.getLeftIndex() <= index && value.getRightIndex() >= index) {
                left.set(value.getLeftIndex());
                right.set(value.getRightIndex());
            }
        });
        if(left.get() != -1 && right.get() != -1) {
            return new IndexRange(left.get(), right.get());
        }

        return null;
    }

    public static void deleteSpecialStyleMessageIfNeeded(int start, int end) {
        currentSpecialStyleMessages.forEach((key, value) -> {
            if(value.getRightIndex() < end && value.getLeftIndex() >=start) {
                currentSpecialStyleMessages.remove(key);
            }
        });
    }

    //在修改发生在文本左侧时移动时移动文本，offset为负数表示左移
    public static void shiftSpecialStyleMessageIndex(int index, int offset) {
        currentSpecialStyleMessages.forEach((key, value) -> {
            System.out.println("左侧索引为 " + value.getLeftIndex());
            System.out.println("右侧索引为 " + value.getRightIndex());
            if(value.getLeftIndex() >= index) {
                value.shiftIndex(offset);
            }
        });
    }

    //切换当前聊天对象时调用
    public static void clearCurrentSpecialStyleMessages() {
        currentSpecialStyleMessages.clear();
        currentSpecialStyleMessageNum.put(FILE_MESSAGE, 0);
        currentSpecialStyleMessageNum.put(AT_MESSAGE, 0);
    }

    public static SpecialStyleMessage getSpecialStyleMessage(String key) {
        return currentSpecialStyleMessages.get(key);
    }

    public static FileMessage getFileMessage(String key) {
        if(currentSpecialStyleMessages.get(key) instanceof FileMessage fileMessage) {
            return fileMessage;
        }
        else {
            return null;
        }
    }

    public static List<FileMessage> getAllFileMessage() {
        //D老师写的
        List<FileMessage> list = new ArrayList<>();
        for(var value : currentSpecialStyleMessages.values()) {
            if(value instanceof FileMessage fileMessage) {
                list.add(fileMessage);
            }
        }

        return list;
    }

    public static Thread getCurrentUpdating(String id) {
        return updatingListMap.get(id);
    }

    public static void rmUpdatingList(String id) {
        updatingListMap.remove(id);
    }

    public static void addUpdatingList(String id, Thread thread) {
        updatingListMap.put(id, thread);
    }

    public static ClientMessage getCurrentAIMessage(String id) {
        return currentAIMessagesMap.get(id);
    }

    public static void rmCurrentAIMessage(String id) {
        currentAIMessagesMap.remove(id);
    }

    public static void addCurrentAIMessage(ClientMessage message) {
        currentAIMessagesMap.put(message.getId(), message);
    }

    public static Path getFilePath () {
        return filePath;
    }

    private static void initAIProperties() {
        try {
            Path projectRoot = getProjectRoot();

            Path configDir = projectRoot.resolve("config");
            Path fileDir = projectRoot.resolve("files");
            Path configPath = configDir.resolve(fileName);
            filePath = Paths.get(configPath.toUri()).toAbsolutePath();

            Files.createDirectories(configDir);
            Files.createDirectories(fileDir);
            if(Files.notExists(configPath)) {
                List<String> defaultContent = Arrays.asList(
                        "# AI配置参数",
                        "AI-type=",
                        "api-key=",
                        "model=",
                        "auto_detect=false",
                        "max_detect=8",
                        "file_storage_path=" + fileDir.toAbsolutePath().toString()
                                .replace("\\", "\\\\")//我恨转义字符
                );

                Files.write(configPath, defaultContent,
                        StandardCharsets.UTF_8,
                        StandardOpenOption.CREATE_NEW);
            }
            else {
                try(InputStream input = Files.newInputStream(filePath)) {
                    Properties properties = new Properties();
                    properties.load(input);
                    AITYPE = properties.getProperty("AI-type");
                    APIKEY = properties.getProperty("api-key");
                    MODEL = properties.getProperty("model");
                    AUTO_DETECT_TEXT = Boolean.parseBoolean(properties.getProperty("auto_detect"));
                    MAX_DETECT_NUM = Integer.parseInt(properties.getProperty("max_detect"));
                    FILE_STORAGE_PATH = properties.getProperty("file_storage_path");
                    Path path = Paths.get(FILE_STORAGE_PATH);
                    FILE_STORAGE_PATH = path.toString();

                }
            }

        } catch (IOException e) {
            /*
            异常处理待优化
             */
            e.printStackTrace();
        }
    }

    public static Path getProjectRoot() {
        String currentDir = System.getProperty("user.dir");
        Path currentPath = Paths.get(currentDir);

        if(currentPath.endsWith("target")) {
            return currentPath.getParent();
        }
        else {
            return currentPath;
        }
    }

    /**
     * 添加连接到连接池
     * @param connectionID 连接标识（例如：BASE_CONNECTION表示基础连接）后续可能添加专门传输文件的线程之类
     * @param newConnection 客户端连接线程对象
     */
    public static void addConnection(String connectionID, ClientConnectThread newConnection){
        if(connectionMap.get(connectionID) != null) {
            connectionMap.get(connectionID).close();
        }
        connectionMap.put(connectionID, newConnection);
    }

    public static ClientConnectThread getConnection(String connectionID){
        return connectionMap.get(connectionID);
    }

    public static void closeConnection(){
        Iterator<Map.Entry<String, ClientConnectThread>> iterator = connectionMap.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<String, ClientConnectThread> entry = iterator.next();
            try {
                entry.getValue().close();
            } finally {
                iterator.remove();
            }
        }
    }

    public static User getChatUser() {
        return chatUser;
    }

    public static void setChatUser(User user) {
        chatUser = user;
        chatGroup = new Group();
    }

    public static void setChatGroup(Group group) {
        chatGroup = group;
        chatUser = new User();
    }

    public static Group getChatGroup() {
        return chatGroup;
    }

    public static User getSpeaker() {
        return speaker;
    }

    public static void setSpeaker(User user) {
        System.out.println("将用户设置为: " + user.getUserName());
        speaker = user;
    }

    public static ObservableList<Group> getGroupList() {
        return groupList;
    }

    public static void addGroupList(Group group) {
        Platform.runLater(() -> {
            for (var i : groupList) {
                if (i.getGroupId() == group.getGroupId()) {
                    i.setGroup(group);
                    return;
                }
            }

            groupList.add(group);

        });
    }

    public static void updateGroupList(Group group) {
        Platform.runLater(() -> {
            for(var i : groupList) {
                if(i.getGroupId() == group.getGroupId()) {
                    group.setGroup(group);
                    MainViewController.getInstance().refreshGroupList();
                    break;
                }
            }
        });
    }

    public static void rmGroup(int groupId) {
        for(var i : groupList) {
            if(i.getGroupId() == groupId) {
                groupList.remove(i);
                return;
            }
        }
    }

    public static void addGroupMember(int groupId, String username) {
        Platform.runLater(() -> {
            for(var i : groupList) {
                if(i.getGroupId() == groupId) {
                    i.addGroupMember(username);
                    return;
                }
            }
        });
    }

    public static void getGroupListFromServer() {
        Message message = new Message();
        message.setMsgType(MessageType.MESSAGE_GROUP_LIST_REQUEST);
        message.setSendUser(getSpeaker().getUserName());
        System.out.println("从服务器请求群组列表,用户名: " + getSpeaker().getUserName());
        try {
            ClientUtils.sendMessage(getConnection(ConnectionType.BASE_CONNECTION).getSocket(), message);
        } catch (IOException e) {
            /*
            异常处理待优化
             */
            e.printStackTrace();
        }
    }

    public static void getCurrentGroupMemberListFromServer() {
        Message message = new Message();
        message.setMsgType(MessageType.MESSAGE_GET_GROUP_MEMBERS);
        message.setSendUser(getSpeaker().getUserName());
        message.setContent(String.valueOf(getChatGroup().getGroupId()));
        try {
            ClientUtils.sendMessage(getConnection(ConnectionType.BASE_CONNECTION).getSocket(), message);
        } catch (IOException e) {
            // 异常处理待优化
            e.printStackTrace();
        }
    }

    public static ObservableList<User> getUserList() {
        return userList;
    }

    public static void setUserList(List<User> list) {
        userList.addAll(list);
    }

    public static void getUserListFromServer() {
        try {
            Message msg = new Message();
            msg.setMsgType(MessageType.MESSAGE_USER_LIST_REQUEST);
            ClientUtils.sendMessage(ServiceUtils.
                    getConnection(ConnectionType.BASE_CONNECTION).getSocket(), msg);
        } catch (IOException e) {
            /*
            后续优化异常处理
             */
            e.printStackTrace();
        }
    }

    public static void addUserList(User user) {
        for(var i : userList) {
            if(i.getUserName().equals(user.getUserName())) {
                i.setUser(user);
                MainViewController.getInstance().refreshUserList();
                MainViewController.getInstance().refreshMemberList();
                return;
            }
        }
        userList.add(user);
    }

    public static void setGroupNotify(int groupId, boolean notify) {
        Platform.runLater(() -> {
            for(var i : groupList) {
                if(i.getGroupId() == groupId) {
                    i.setNotify(notify);
                    MainViewController.getInstance().refreshGroupList();
                    break;
                }
            }
        });
    }

    public static void setNotify(String username, boolean notify) {
        Platform.runLater(() -> {
            for(var i : userList) {
                if(i.getUserName().equals(username)) {
                    i.setNotify(notify);
                    MainViewController.getInstance().refreshUserList();
                    break;
                }
            }
        });
    }

    public static void setMessageList(List<ClientMessage> list) {
        List<ClientMessage> rmList = new ArrayList<>();
        for (var i : list) {
            if (i.getId().equals(chatUser.getUserName())
                    || i.getId().equals(String.valueOf(chatGroup.getGroupId()))) {
                rmList.add(i);
            }
        }

        for(var i : rmList) {
            list.remove(i);
        }

        Platform.runLater(() -> {
            messageList.clear();
            messageList.addAll(list);
        });
    }

    public static void addMessageList(Message message) {
        Platform.runLater(() -> {
            messageList.add(new ClientMessage(message));
            insertMessageIntoMessageTables(getTheOtherOne(message), message);
        });
    }

    public static void addMessageList(ClientMessage message) {
        Platform.runLater(() -> {
            messageList.add(message);
            insertMessageIntoMessageTables(getTheOtherOne(message), message);
        });
    }

    public static ObservableList<ClientMessage> getMessageList() {
        return messageList;
    }

    public static void clearMessageList() {
        Platform.runLater(messageList::clear);
    }

    public static void getFriendRequestFromServer() {
        Message message = new Message();
        message.setMsgType(MessageType.MESSAGE_GET_FRIEND_REQUEST);
        message.setSendUser(getSpeaker().getUserName());
        try {
            ClientUtils.sendMessage(getConnection(ConnectionType
                    .BASE_CONNECTION).getSocket(), message);
        } catch (IOException e) {
            /*
            异常处理待优化
             */
            e.printStackTrace();
        }
    }

    public static void getMessageListFromServer() {
        UsernameOrGroupId key;
        if(getChatUser().getUserName() != null) {
            key = new UsernameOrGroupId(getChatUser().getUserName());
        }
        else {
            key = new UsernameOrGroupId(getChatGroup().getGroupId());
        }

        if(getMessageTable(key) != null) {
            setMessageList(getMessageTable(key));
            return;
        }

        Message message = new Message();
        message.setMsgType(MessageType.MESSAGE_MESSAGE_LIST_REQUEST);
        message.setSendUser(getSpeaker().getUserName());
        if(getChatUser().getUserName() != null) {
            message.setReceiveUser(getChatUser().getUserName());
        }
        else {
            message.setReceiveUser(String.valueOf(getChatGroup().getGroupId()));
        }

        try {
            ClientUtils.sendMessage(getConnection(ConnectionType.BASE_CONNECTION).getSocket(), message);
        } catch (IOException e) {
            /*
            异常处理待优化
             */
            e.printStackTrace();
        }
    }

    public static void createGroup() {
        ClientUtils.showCreateGroupPage();
    }

    public static void joinGroup() {
        ClientUtils.showJoinGroupPage();
    }

    public static boolean isInteger(String str) {
        try {
            Integer.parseInt(str);
        } catch(Exception e) {
            return false;
        }
        return true;
    }

    public static boolean waitingToBeUpdate() {
        for (var i : messageList) {
            if(i.getId().equals(chatUser.getUserName())
                    || i.getId().equals(String.valueOf(chatGroup.getGroupId()))) {
                return true;
            }
        }
        return false;
    }

    /*
    判断是否是未加载完成的AI消息，三个判断分支
    1、如果没有待更新的“AI小助手正在思考”且当前更新队列中也不包含该消息，则认为该消息是历史AI消息，已经加载完成
    2、若存在待更新的AI小助手正在思考，且当前队列中不存在该消息，则认为该消息是从头开始加载的AI消息，
    将其添加到更新队列，启动更新线程
    3、若不存在待更新的AI小助手正在思考，且当前队列中存在该消息，则认为该消息是加载到一半的AI消息，重启更新线程
    由于消息接收机制改变，第三条现已事实上废弃(不再会进入该分支
     */
    public static void addAIMessage(Message message) {
        System.out.println("收到消息的ID为: " + message.getId());

        if(!currentAIMessagesMap.containsKey(message.getId())
                && !waitingToBeUpdate()) {
            if(message.getSendUser().equals(chatUser.getUserName())
                    || message.getSendUser().equals(String.valueOf(chatGroup.getGroupId()))) {
                addMessageList(message);
            }
            else {
                ClientMessage newMessage = new ClientMessage();
                newMessage.setClientMessage(message);
                newMessage.getContentProperty().set(message.getContent());
                newMessage.setComplete();
                insertMessageIntoMessageTables(new UsernameOrGroupId(message.getSendUser()), newMessage);
            }
            return;
        }
        //确保messageList加载完毕
        int size;
        try {
            do{
                size = messageList.size();
                Thread.sleep(10);
            }while (size != messageList.size());
        } catch (InterruptedException e) {
            /*
            无需处理
             */
            e.printStackTrace();
        }

        for(var i : messageList) {
            if(i.isAI() && !i.isCompleteProperty().get()
                    && ( currentAIMessagesMap.containsKey(message.getId())
                    || waitingToBeUpdate())
            ) {
                i.setClientMessage(message);
                ClientMessage newMessage = new ClientMessage();
                newMessage.setClientMessage(message);
                newMessage.getContentProperty().set(message.getContent());
                newMessage.setComplete();
                insertMessageIntoMessageTables(new UsernameOrGroupId(message.getSendUser()), newMessage);
                if(!currentAIMessagesMap.containsKey(message.getId())) {
                    addCurrentAIMessage(i);
                    MainViewController.getInstance().refreshMessageList();
                    return;
                }
            }
        }

        if(updatingMessageIndex.containsKey(message.getId())) {
            ClientMessage cm = new ClientMessage();
            cm.setClientMessage(message);
            cm.setCurrentDisplayIndex(updatingMessageIndex.get(message.getId()));
            cm.getContentProperty().set(cm.getOriginContent().substring(0, cm.getCurrentDisplayIndex()));

            Platform.runLater(() -> {
                messageList.add(cm);
                Thread thread = new Thread(() -> updateAIMessage(cm));
                thread.start();
                addUpdatingList(cm.getId(), thread);
            });
        }
    }

    public static String currentChatUpdatingId() {
        AtomicReference<String> re = new AtomicReference<>();
        if(chatUser.getUserName() != null) {
            currentAIMessagesMap.forEach((key, value) -> {
                if(value.getSendUser().equals(chatUser.getUserName())) {
                    re.set(value.getId());
                }
            });
        }
        else {
            currentAIMessagesMap.forEach((key, value) -> {
                if(value.getSendUser().equals(String.valueOf(chatGroup.getGroupId()))) {
                    re.set(value.getId());
                }
            });
        }
        return re.get();
    }

    public static void updateAIMessage(ClientMessage message) {
        if(currentAIMessagesMap.get(message.getId()) == null) {
            return;
        }

        int index = message.getCurrentDisplayIndex();

        for( ; index < message.getOriginContent().length(); index++) {
            message.updateContent(String.valueOf(message.getOriginContent().charAt(index)));
            message.setCurrentDisplayIndex(index);
            try {
                Thread.sleep(25);
            } catch (InterruptedException e) {
                updatingMessageIndex.put(message.getId(), message.getCurrentDisplayIndex());
                e.printStackTrace();
            }
        }

        rmCurrentAIMessage(message.getId());
        rmUpdatingList(message.getId());
        updatingMessageIndex.remove(message.getId());
    }

    public static String imageIsHovered(int hoverIndex) {

        if(currentSpecialStyleMessageNum.get(FILE_MESSAGE) == 0) {
            return null;
        }

        return currentSpecialStyleMessages.search(1, (key, value) -> {
            if(!(value instanceof FileMessage fileMessage)) {
                return null;
            }

            boolean isImage = fileMessage.getFilePath().endsWith(".jpg")
                    || fileMessage.getFilePath().endsWith(".png");

            if(!isImage) {
                return null;
            }

            if(hoverIndex > fileMessage.getLeftIndex() && hoverIndex < fileMessage.getRightIndex()) {
                return fileMessage.getFilePath();
            }
            else {
                return null;
            }
        });
    }

    //试一下idea的注解，其实没什么用

    public static boolean doSpecialStyleTextExist() {
        return !currentSpecialStyleMessages.isEmpty();
    }

    //创建文件传输通道
    public static void createFileConnection() throws IOException, ClassNotFoundException, FileConnectionException {
        Socket socket = new Socket(ServiceUtils.serverAddress, ServiceUtils.serverPort);

        Message message = new Message();
        message.setMsgType(MessageType.MESSAGE_CREATE_FILE_CONNECTION_REQUEST);
        message.setContent(speaker.toString());
        ClientUtils.sendMessage(socket ,message);

        ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
        Message msg = (Message) ois.readObject();
        String status = msg.getMsgType();
        if(!MessageType.MESSAGE_CREATE_FILE_CONNECTION_REQUEST.equals(status)) {
            throw new FileConnectionException("文件传输通道建立失败");
        }

        ClientConnectThread clientConnectThread = new ClientConnectThread(socket);
        clientConnectThread.start();
        ServiceUtils.addConnection(ConnectionType.FILE_CONNECTION, clientConnectThread);
    }

    public static void closeFileConnection() throws IOException {
        if(ServiceUtils.getConnection(ConnectionType.FILE_CONNECTION) != null) {
            ServiceUtils.getConnection(ConnectionType.FILE_CONNECTION).getSocket().close();
        }
    }

    public static boolean isDouble(String str) {
        try {
            Double.parseDouble(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

}
